package org.fhawk.tinyspring.orm;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.StringUtils;
import org.fhawk.tinyspring.core.ConfigHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;

/**
 *
 */
public class ConnectionFactory {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionFactory.class);

    //从配置文件中获取数据库配置
    private static String driver = ConfigHelper.getString("org.fhawk.jdbc.driver");
    private static String url = ConfigHelper.getString("org.fhawk.jdbc.url");
    private static String username = ConfigHelper.getString("org.fhawk.jdbc.username");
    private static String password = ConfigHelper.getString("org.fhawk.jdbc.password");
    //从配置文件中获取的初始化脚本
    private static String initSql = ConfigHelper.getString("org.fhawk.init.sql");
    //默认的初始化脚
    private static final String DEFAULT_INIT_SQL = "data.sql";

    private static final BasicDataSource DATA_SOURCE;

    private ConnectionFactory() {
    }

    static {
        //初始化datasource
        DATA_SOURCE = new BasicDataSource();
        DATA_SOURCE.setDriverClassName(driver);
        DATA_SOURCE.setUrl(url);
        DATA_SOURCE.setUsername(username);
        DATA_SOURCE.setPassword(password);
        initSql();
    }

    /**
     * 用于保存当前线程的连接
     */
    private static ThreadLocal<Connection> connection = new ThreadLocal<>();

    /**
     * 获取连接
     *
     * @return 数据库链接
     */
    static Connection getConnection() throws SQLException {
        Connection conn = connection.get();
        if (null == conn) {
            try {
                conn = DATA_SOURCE.getConnection();
                connection.set(conn);
            } catch (SQLException e) {
                LOGGER.error("get connection fail", e);
                throw e;
            }
        }
        return conn;
    }

    /**
     * 开启事务
     */
    public static void beginTransaction() throws SQLException {
        getConnection().setAutoCommit(false);
    }

    /**
     * 提交事务
     */
    public static void commit() throws SQLException {
        getConnection().commit();
    }

    /**
     * 关闭链接
     */
    public static void close() {
        try {
            getConnection().close();
        } catch (SQLException e) {
            LOGGER.error("关闭数据库链接失败。", e);
        } finally {
            connection.remove();
        }
    }

    /**
     * 事务回滚
     */
    public static void rollback() throws SQLException {
        try {
            Connection conn = getConnection();
            conn.rollback();
            conn.close();
        } finally {
            connection.remove();
        }
    }

    /**
     * 初始化数据库
     */
    private static void initSql() {
        URL initSqlPath = Thread.currentThread().getClass().getClassLoader().getResource(StringUtils.isEmpty(initSql) ? DEFAULT_INIT_SQL : initSql);
        try {
            if (!Objects.isNull(initSqlPath)) {
                Path initFile = Paths.get(initSqlPath.toURI());
                if (!initFile.toFile().exists()) {
                    return;
                }
                List<String> sqls = Files.readAllLines(initFile);
                for (String sql : sqls) {
                    try (PreparedStatement statement = getConnection().prepareStatement(sql)) {
                        statement.execute();
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("执行初始化SQL失败。", e);
        }
    }
}
